package component.controls.loader
{
	import component.controls.interfaces.IDispose;
	import component.global.manager.EventMgr;
	import component.global.utils.DisplayUtils;
	import component.global.utils.ObjectUtil;
	
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	
	[Event(name="complete",type="loaders.LoaderEvent")]
	[Event(name="progress",type="loaders.LoaderEvent")]
	[Event(name="error",type="loaders.LoaderEvent")]
	
	public class BaseLoader extends EventDispatcher implements IDispose
	{
		/**
		 * 二进制loader 
		 */		
		public static const BINARY_LOADER:String = "binaryLoader";
		
		/**
		 * 文本loader
		 */		
		public static const TEXT_LOADER:String = "textLoader";
		
		
		public static const BITMAP_LOADER:String = "bitmapLoader";
		
		/**
		 * 最大错误数,用来限制loader重新加载的次数 
		 */		
		public static const MAX_ERROR_COUNT:int = 2;
		
		/**
		 * 底层loader 
		 * @param url 请求的url路径
		 * @param variables 请求参数
		 * @param method 请求方法 GET 或者 POST
		 * 
		 */		
		public function BaseLoader(url:String,variables:URLVariables = null, method:String = URLRequestMethod.GET)
		{
			_url = url;
			_urlVariables = variables;
			_requestMethod = method;
			initLoader();
		}
		
		protected var _loader:Loader;
		protected var _urlLoader:URLLoader;
		protected var _request:URLRequest;
		protected var _url:String;
		protected var _requestMethod:String;
		protected var _urlVariables:URLVariables;
		protected var _isComplete:Boolean;
		protected var _isLoading:Boolean;
		protected var _progress:int;
		protected var _errorMessage:String;
		protected var _errorCount:int;
		protected var _completeFunc:Function;
		
		public function get url():String{
			return _url;
		}
		
		public function get isSuccess():Boolean{
			return _isComplete && (_progress == 100);
		}
		
		/**
		 * 是否加载完成 
		 * @return  布尔值
		 * 
		 */		
		public function get isComplete():Boolean{
			return _isComplete;
		}
		
		/**
		 * 是否正在加载 
		 * @return  布尔值
		 * 
		 */		
		public function get isLoading():Boolean{
			return _isLoading;
		}
		
		/**
		 * 加载进度 
		 * @return  0 - 100 的整型
		 * 
		 */		
		public function get progress():int{
			return _progress;
		}
		
		/**
		 * 错误描述信息 
		 * @return  错误字符串
		 * 
		 */		
		public function get errorMessage():String{
			return _errorMessage;
		}
		
		/**
		 * loader 的类型
		 * @return 类型字符串
		 * 
		 */		
		public function get type():String{
			return BaseLoader.BINARY_LOADER;
		}
		
		/**
		 * 取得loader加载后得到的数据
		 * @return 返回的数据类型与loader 的类型相关
		 * 
		 */		
		public function get content():*{
			return _urlLoader.data;
		}
		
		/**
		 * 发出请求并加载
		 * @param url  要发出的请求的url, 如不传入则使用实例化loader时的url,
		 * 
		 */		
		public function load(url:String = null):void{
			_isLoading = true;
			if(url)_url = url;
			if(!_url){
				_isComplete = true;
				_isLoading = false;
				_errorMessage = "url cannot be null!";
				dispatch(LoaderEvent.ERROR);
				dispatch(LoaderEvent.COMPLETE);
				return;
			}
			_request = new URLRequest(_url + "?random=" + Math.floor(Math.random()* 9999));
			_request.method = _requestMethod;
			_request.data = _urlVariables;
			_urlLoader.dataFormat = dataFormat();
			_urlLoader.load(_request);
		}
		
		/**
		 * 抛出事件 
		 * @param type  事件类型字符串
		 * 
		 */		
		public function dispatch(type:String):void{
			dispatchEvent(new LoaderEvent(type, this));
		}
		
		/**
		 * 设置完成后执行的方法, 非强制属性
		 * @param func
		 * 
		 */		
		public function set completeFunc(func:Function):void{
			if(func != null)_completeFunc = func;
		}
		
		protected function dataFormat():String{
			return URLLoaderDataFormat.BINARY;
		}
		
		protected function initLoader():void{
			_urlLoader = new URLLoader();
			EventMgr.Instance.addEvent(_urlLoader, [Event.COMPLETE,HTTPStatusEvent.HTTP_STATUS,ProgressEvent.PROGRESS,IOErrorEvent.IO_ERROR],[__onComplete,__onHTTPStatus,__onProgress,__onIOError]);
		}
		
		protected function __onComplete(e:Event):void{
			_isComplete = true;
			_isLoading = false;
			if(_completeFunc != null)_completeFunc(content);
			dispatch(LoaderEvent.PROGRESS);
			dispatch(LoaderEvent.COMPLETE);
			EventMgr.Instance.removeEvent(_urlLoader, [Event.COMPLETE,HTTPStatusEvent.HTTP_STATUS,ProgressEvent.PROGRESS,IOErrorEvent.IO_ERROR],[__onComplete,__onHTTPStatus,__onProgress,__onIOError]);
		}
		
		protected function __onProgress(e:ProgressEvent):void{
			_progress = Math.round(100 * (_urlLoader.bytesLoaded / _urlLoader.bytesTotal ));
			dispatch(LoaderEvent.PROGRESS);
		}
		
		protected function __onHTTPStatus(e:HTTPStatusEvent):void{
			if(e.status > 399){
				_errorCount++;
				if(_errorCount >= MAX_ERROR_COUNT){
					_errorMessage = "HTTP Status returned not valid!"
					dispatch(LoaderEvent.ERROR);
					dispatch(LoaderEvent.COMPLETE);
				} else {
					load();
				}
			}
		}
		
		protected function __onIOError(e:IOErrorEvent):void{
			_errorCount++;
			if(_errorCount >= MAX_ERROR_COUNT){
				_isComplete = true;
				_isLoading = false;
				_errorMessage = "io Error! url=" + _url;
				dispatch(LoaderEvent.ERROR);
				dispatch(LoaderEvent.COMPLETE);
			} else {
				load();
			}
		}
		
		public function dispose():void{
			if(_loader){
				ObjectUtil.dispose(_loader.contentLoaderInfo);
				_loader.unloadAndStop();
//				ObjectUtil.dispose(_loader);_loader = null;
			}
			
			ObjectUtil.dispose(_urlLoader);_urlLoader = null;
			ObjectUtil.dispose(_request);_request = null;
			ObjectUtil.dispose(_urlVariables);_urlVariables = null;
			_completeFunc = null;
		}
	}
}